from config import *
from mine import Mine
import random


class GameManager(object):
    """
    游戏管理器
    """
    def __init__(self, screen):
        self.mine_map = [] # 地雷对象数组
        self.screen = screen # 屏幕对象

        # 初始化地雷数组
        self.init_mine()

        # 随机埋炸弹
        self.random_gen_bomb()

    def __str__(self):
        result = ""
        for y in range(BLOCK_HEIGHT):
            for x in range(BLOCK_WIDTH):
                t = self.mine_map[y * BLOCK_WIDTH + x]
                str = "%s" % t
                result += str + "\t"
            result += "\n"
        return result

    def init_mine(self):
        """初始化地雷数组"""
        for i in range(BLOCK_HEIGHT * BLOCK_WIDTH):
            mine = Mine(i % BLOCK_WIDTH, i // BLOCK_WIDTH)
            self.mine_map.append(mine)

    def random_gen_bomb(self):
        """随机生成炸弹"""
        for i in random.sample(range(BLOCK_WIDTH * BLOCK_HEIGHT), BOMB_COUNT):
            self.mine_map[i].set_bomb()

        # debug_mine_map = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        #                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]
        #
        # for i, flag in enumerate(debug_mine_map):
        #     if flag:
        #         self.mine_map[i].set_bomb()

    def draw_mine_map(self):
        """绘制地雷地图"""

        # 填充背景色
        self.screen.fill(bgcolor)

        # 绘制地雷地图
        for i in range(BLOCK_HEIGHT * BLOCK_WIDTH):
            mine = self.mine_map[i]
            mine.draw(self.screen)

    def pos_2_id(self, x, y):
        """
        逻辑坐标转地雷数组索引
        :param x: 逻辑x坐标
        :param y: 逻辑y坐标
        :return: 地雷数组索引
        """
        return y * BLOCK_WIDTH + x

    def get_mine(self, x, y):
        """
        根据逻辑xy坐标获取地雷对象
        :param x: 逻辑x坐标
        :param y: 逻辑y坐标
        :return: 地雷对象
        """
        return self.mine_map[self.pos_2_id(x, y)]

    def game_over(self, x, y):
        """
        踩到地雷游戏结束
        :param x: 踩到的地雷逻辑x坐标
        :param y: 踩到的地雷逻辑y坐标
        """
        # 1. 显示所有的地雷
        for mine in self.mine_map:
            if mine.is_bomb():
                mine.show_bomb()

        # 2. 显示踩到的地雷
        mine = self.get_mine(x, y)
        mine.show_die()

    @classmethod
    def get_neighbor_pos(cls, x, y):
        """获取邻居的逻辑坐标"""
        pos_list = ((x - 1, y - 1), (x, y - 1), (x + 1, y - 1),
                    (x - 1, y), (x + 1, y),
                    (x - 1, y + 1), (x, y + 1), (x + 1, y + 1))

        result = []

        for pos in pos_list:
            x = pos[0]
            y = pos[1]
            if 0 <= x < BLOCK_WIDTH and 0 <= y < BLOCK_HEIGHT:
                result.append((x, y))

        return tuple(result)

    def check_bomb_around(self, x, y):
        """检查周围的地雷数量"""
        count = 0 # 统计当前点击位置周围的地雷数量
        for pos in self.get_neighbor_pos(x, y):
            mine = self.get_mine(pos[0], pos[1])
            if mine.is_bomb():
                count += 1

        return count

    def left_click(self, x, y):
        """鼠标左键点击"""
        mine = self.get_mine(x, y)
        if mine.is_bomb(): # 如果踩到了地雷
            self.game_over(x, y) # 游戏结束
        else: # 如果没有踩到地雷
            # 判定周围的地雷有几个
            num = self.check_bomb_around(x, y)

            # 显示周围的地雷数量
            if num > 0:
                mine.show_around_num(num)
            else:
                # 如果周围的地雷数量是0，则把周围相邻的0全部找出来
                self.find_0(x, y)

    def right_click(self, x, y):
        """鼠标右键点击"""
        print("鼠标右键点击[%d,%d]" % (x, y))

    def find_0(self, x, y):
        """递归搜索相邻的0"""
        mine = self.get_mine(x, y)

        if mine.state is not Mine.HIDE:
            return

        mine.show_around_num(0)  # 显示自己的状态为0

        for pos in self.get_neighbor_pos(x, y): # 搜索自己周围的地雷
            mine = self.get_mine(pos[0], pos[1])
            if mine.state is not Mine.HIDE:
                continue
            num = self.check_bomb_around(pos[0], pos[1])
            if num == 0:
                self.find_0(pos[0], pos[1])
            else:
                mine.show_around_num(num)



